/**
 * MOTOR 2 - RAPID FLASH DYNAMICS
 * Copyright (c) 2007-2008, Michael Baczynski
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * * Neither the name of the polygonal nor the names of its contributors may be
 *   used to endorse or promote products derived from this software without specific
 *   prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package de.polygonal.motor2.collision.nbody
{
	import flash.utils.Dictionary;
	
	import de.polygonal.motor2.collision.nbody.IPairCallback;
	import de.polygonal.motor2.collision.nbody.Pair;
	import de.polygonal.motor2.collision.nbody.ShapeProxy;
	import de.polygonal.motor2.collision.shapes.ShapeSkeleton;
	import de.polygonal.motor2.dynamics.contact.Contact;	

	/**
	 * checks every possible pair against each other
	 * time complexity: n(n-1)/2 ~ O(n^2)
	 */
	public class ExhaustiveSearch extends BroadPhase
	{
		public function ExhaustiveSearch()
		{
			_pairs = new Dictionary(true);
		}
		
		public var _pairs:Dictionary;
		
		override public function insideBounds(xmin:Number, ymin:Number, xmax:Number, ymax:Number):Boolean
		{
			return true;
			
			//TODO
			if (xmin < _xmin) return false;
			if (xmax > _xmax) return false;
			if (ymin < _ymin) return false;
			if (ymax > _ymax) return false;
		}
		
		override public function search():void
		{
			var p1:ShapeProxy, s1:ShapeSkeleton, proxyId1:int;
			var p2:ShapeProxy, s2:ShapeSkeleton, proxyId2:int;
			
			var c:Contact;
			var hash:int;
			
			p1 = proxyList;
			while (p1)
			{
				proxyId1 = p1.id;
				s1 = p1.shape;
				
				p2 = p1.next;
				
				while (p2)
				{
					proxyId2 = p2.id;
					s2 = p2.shape;
					
					
					//collision filtering
					if (p1.groupIndex == p2.groupIndex)
						if (p1.groupIndex != 0)
							if (p1.groupIndex <= 0)
								continue;
					
					if ((p1.maskBits & p2.categoryBits) == 0) continue;
					if ((p1.categoryBits & p2.maskBits) == 0) continue;
					if (s1.xmin > s2.xmax || s1.xmax < s2.xmin || s1.ymin > s2.ymax || s1.ymax < s2.ymin)
					{
						/* aabb separated */
						if (p1.overlapCount > 0 && p2.overlapCount > 0)
						{
							if (proxyId1 < proxyId2)
								hash = (proxyId1 << 16) | (proxyId2 << 8);
							else
								hash = (proxyId2 << 16) | (proxyId1 << 8);
							
							var pair:Pair = _pairs[hash];
							if (pair)
							{
								p1.overlapCount--;
								p2.overlapCount--;
								
								_pairHandler.pairRemoved(proxyId1, proxyId2, pair.userData as Contact);
								_pairs[hash] = undefined;
							}
						}
					}
					else
					{
						/* aabb intersecting */
						if (proxyId1 < proxyId2)
							hash = (proxyId1 << 16) | (proxyId2 << 8);
						else
							hash = (proxyId2 << 16) | (proxyId1 << 8);
						
						if (_pairs[hash] == undefined)
						{
							p1.overlapCount++;
							p2.overlapCount++;
							
							c = _pairHandler.pairAdded(s1, s2);
							_pairs[hash] = new Pair(proxyId1, proxyId2, c);
						}
					}
					
					p2 = p2.next;
				}
				
				p1 = p1.next;
			}
		}
	}
}